const EventEmitter = require('events');
const fs = require('fs');

class ReadStream extends EventEmitter{
  constructor(path, options = {}) {
    super();
    this.path = path;
    this.flags = options.flags || 'r';
    this.encoding = options.encoding || null;
    this.autoClose = options.autoClose || true;
    this.start = options.start || 0;
    this.end = options.end || undefined;
    this.highWaterMark = options.highWaterMark || 64 * 1024;

    this.pos = this.start;
    this.buffer = Buffer.alloc(this.highWaterMark);

    // 可读流默认叫非流动模式
    this.flowing = null;
    this.close = false;

    // new完以后就会打开文件(不论你监听data事件没有) TODO 1
    this.open();

    this.on('newListener', (type) => {
      //当用户rs.on('data'的时候，就会立即执行以下代码 TODO 2
      if(type === 'data'){
        this.flowing = true; //已经开始读取文件了
        this.read(); //开始读取数据
      }
    });
  }

  pause(){
    this.flowing = false;
  }

  resume(){
    if (!this.flowing ) {
      this.flowing = true;
      this.read();
    }
  }

  read(){
    //什么时候能拿到this.fd?
    //读取文件，需要等待触发open事件后再执行
    if (typeof this.fd !== 'number') {
      return this.once('open', () => this.read());
    }

    //考虑到可以指定end，即读取到第几个字节结束读取，我们需要计算this.highWaterMark，以防最后一次读取过度的字节数
    let howMutchToRead = this.end ? Math.min(this.end - this.pos + 1, this.highWaterMark) : this.highWaterMark;

    // console.log('this.fd:',this.fd, 'this.buffer:',this.buffer, '0',0, 'howMutchToRead:',howMutchToRead, 'this.pos:',this.pos);
    fs.read(this.fd, this.buffer, 0, howMutchToRead, this.pos, (err, bytesRead) => {
      // console.log('bytesRead',bytesRead);
      if (bytesRead > 0 ) {
        if(this.flowing){
          this.pos += bytesRead;
          const b = this.buffer.slice(0, bytesRead);
          // console.log('b.toString(this.encoding):',b.toString(this.encoding));
          this.emit('data', this.encoding ? b.toString(this.encoding) : b);
          this.read();
        }
      } else {
        this.emit('end');
        if (this.autoClose) {
          fs.close(this.fd, () => {
            if(!this.close){
              this.emit("close");
              this.close = true; //防止最后一次读取时调用了pause，然后又调用resume触发read()，导致多次触发close事件
            }
          });
        }
      }
    });
  }

  open(){
    fs.open(this.path, this.flags, (err, fd) => {
      if (err) { //有可能文件路径有误 就会触发error事件 不会触发close事件(文件根本没有打开)
        return this.emit('error', err);
      }
      this.fd = fd;
      this.emit('open', fd); //会触发open事件，这时能拿到fd了
    });
  }

  pipe(ws){
    this.on('data', (data) => {
      let flag = ws.write(data);
      if (!flag) {
        this.pause();
      }
    });

    ws.on('drain', () => {
      this.resume();
    });
  }
}

module.exports = ReadStream;
